the inefficent loop
This loop runs through the netcdf files and then looks for which rows in data_aea it should extract the value to point from, and at what depth (netcDF layer)
Start with 2007_10 data
strt <- Sys.time() #get the start time
xy <- testbglist[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbglistsp <- SpatialPointsDataFrame(coords = xy, data = testbglist, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 2007 # a variable for the observation year
mth <- 10 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbglistsp)) {
de <- testbglistsp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbglistsp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$temp_depth[j] <- NA
} else
testbglistsp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbglistsp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$salinity_depth[j] <- NA
} else
testbglistsp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbglistsp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$chl_depth[j] <- NA
} else
testbglistsp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbglistsp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$o2_depth[j] <- NA
} else
testbglistsp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbglistsp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbglistsp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
}
}
}
write.csv(testbglistsp, "../data/env/background_point_check/200710_allbackgroundpoints.csv", row.names = FALSE)
test_back_df <- as.data.frame(testbglistsp)
print(Sys.time()-strt) #time it took to run
ok now create the first lot of random for 2007_10
testbk10000 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk20000 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk50000 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk100000 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk190000 <- test_back_df[sample(nrow(test_back_df), 190000), ]
plot each variable against the different no of background points
ggplot(testbk10000, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Sea Surface Height Above Geoid (meters)")
dev.copy(png, "../output/env/background_point_check/200710_ssh_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Mixed layer thickness (MLP) (meters)")
dev.copy(png,"../output/env/background_point_check/200710_mlp_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Temperature at surface (kelvin)")
dev.copy(png,"../output/env/background_point_check/200710_temp_surface_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Temperature at sampling depth (kelvin)")
dev.copy(png,"../output/env/background_point_check/200710_temp_depth_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Salinity at surface (kelvin)")
dev.copy(png,"../output/env/background_point_check/200710_salinity_surface_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Salinity at sampling depth (kelvin)")
dev.copy(png,"../output/env/background_point_check/200710_salinity_depth_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Chlorophyll concentration at surface (mmol.m-3)")
dev.copy(png,"../output/env/background_point_check/200710_chl_surface_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Chlorophyll concentration at sampling depth (mmol.m-3)")
dev.copy(png,"../output/env/background_point_check/200710_chl_depth_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Dissolved oxygen concentration at surface (mmol.m-3)")
dev.copy(png,"../output/env/background_point_check/200710_o2_surface_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk10000, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Dissolved oxygen concentration at sampling depth (mmol.m-3)")
dev.copy(png,"../output/env/background_point_check/200710_o2_depth_back_no.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
Try again for another month - say 1999 02 AND again 2014 06
This time extract the values for all points and then subset
strt <- Sys.time() #get the start time
xy <- testbglist[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbglistsp <- SpatialPointsDataFrame(coords = xy, data = testbglist, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 1999 # a variable for the observation year
mth <- 02 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbglistsp)) {
de <- testbglistsp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbglistsp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$temp_depth[j] <- NA
} else
testbglistsp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbglistsp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$salinity_depth[j] <- NA
} else
testbglistsp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbglistsp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$chl_depth[j] <- NA
} else
testbglistsp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbglistsp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$o2_depth[j] <- NA
} else
testbglistsp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbglistsp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbglistsp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
}
}
}
write.csv(testbglistsp, "../data/env/background_point_check/199902_allbackgroundpoints.csv", row.names = FALSE)
test_back_df <- as.data.frame(testbglistsp)
print(Sys.time()-strt) #time it took to run
ok now create the first lot of random for 1999_02
testbk10000 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk20000 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk50000 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk100000 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk190000 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk10000, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink") + labs(x = "Sea Surface Height Above Geoid (meters)")
dev.copy(png,"../output/env/background_point_check/199902_ssh_back.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

And now 2014_06
strt <- Sys.time() #get the start time
xy <- testbglist[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbglistsp <- SpatialPointsDataFrame(coords = xy, data = testbglist, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 2014 # a variable for the observation year
mth <- 06 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbglistsp)) {
de <- testbglistsp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbglistsp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$temp_depth[j] <- NA
} else
testbglistsp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbglistsp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$salinity_depth[j] <- NA
} else
testbglistsp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbglistsp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$chl_depth[j] <- NA
} else
testbglistsp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbglistsp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$o2_depth[j] <- NA
} else
testbglistsp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbglistsp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbglistsp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
}
}
}
write.csv(testbglistsp, "../data/env/background_point_check/201406_allbackgroundpoints.csv", row.names = FALSE)
test_back_df <- as.data.frame(testbglistsp)
print(Sys.time()-strt) #time it took to run
ok now create the first lot of random for 2014_06
testbk10000 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk20000 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk50000 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk100000 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk190000 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk10000, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_ssh.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_mlp.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_temp_surface.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_temp_depth.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_salinity_surface.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_salinity_depth.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_chl_surface.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_chl_depth.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_o2_surface.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(testbk10000, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk20000 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk50000 , na.rm = TRUE, colour = "green") + geom_density(data=testbk100000 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_o2_depth.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

LS0tDQp0aXRsZTogImJhY2tncm91bmQgcG9pbnRzIC0gaXMgbW9yZSBiZXR0ZXI/Ig0KYXV0aG9yOiAiU2FtYW50aGEgQW5kcmV3cyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KIyBPdmVydmlldw0KcXVpY2sgdGVzdCB0byBzZWUgd2hhdCBoYXBwZW5zIHRvIGRpc3RyaWJ1dGlvbiBvZiBlbnYuIHZhcmlhYmxlcyBpZiBhZGQgbW9yZSBiYWNrZ3JvdW5kIHBvaW50cyAoaXMgMTBrIGVub3VnaCBvciBkbyBJIG5lZWQgbW9yZSkNCg0KQSBub3RlIHRvIGFueW9uZSB3aG8gbWlnaHQgaGFwcGVuIHRvIHN0dW1ibGUgYWNyb3NzIHRoaXMuLi4gSSBhbSBhIGJlZ2lubmVyIGluIFIgYW5kIGhhdmUgaGFkIG5vIGV4cG9zdXJlIHRvIHNpbWlsYXIgbGFuZ3VhZ2VzLiBJIGRvbid0IGtub3cgd2hhdCBJJ20gZG9pbmcuIFRoZSBjb2RlIGhlcmVpbiBpcyB1bmxpa2VseSB0byBiZSBlbGVnYW50IGFuZCB0aGVyZSBhcmUgcHJvYmFibHkgbW9yZSBlZmZpY2llbnQgd2F5cyBvZiBydW5uaW5nIHRoZSBjb2RlLg0KDQpCdWlsdCB3aXRoICdyIGdldFJ2ZXJzaW9uKCknLg0KDQojIFBhY2thZ2UgZGVwZW5kZW5jaWVzDQpZb3UgY2FuIGxvYWQgdGhlbSB1c2luZyB0aGUgZm9sbG93aW5nIGNvZGUgd2hpY2ggdXNlcyBhIGZ1bmN0aW9uIGNhbGxlZCBbaXBha10oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vc3RldmVud29ydGhpbmd0b24vMzE3ODE2MykuIA0KTm90ZSB0aGlzIGZ1bmN0aW9uIGNoZWNrcyB0byBzZWUgaWYgdGhlIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQgZmlyc3QuDQpUaGUgImluY2x1ZGU9RkFMU0UiIHN1cHJlc3NlcyB0aGUgcGFja2FnZSBpbnN0YWxsYXRpb24gdGV4dCBhcHBlYXJpbmcgaW4gdGhlIGRvY3VtZW50Li4uDQpgYGB7ciBwcmUtaW5zdGFsbCBwYWNrYWdlcywgaW5jbHVkZT1GQUxTRX0NCnBhY2thZ2VzIDwtIGMoIm5jZGY0IiwgInJhc3RlciIsICJnZ3Bsb3QyIiwgInBsb3RseSIpIA0Kc291cmNlKCIuLi9zcmMvaXBhay5SIikNCmlwYWsocGFja2FnZXMpDQpgYGANCg0KbG9hZCB0aGUgcmF3IGJhY2tncm91bmQuY3N2IGZpbGUgd2l0aCBhbGwgcG9pbnRzIHRvIHJhbmRvbWx5IGV4dHJhY3QgcG9pbnRzIGZyb20gKC4uL291dHB1dC9lbnYvdW5pcXVlX2NlbGxfY2VudHJvaWRfbG9ubGF0X25hZm8yX2RlcHRoLmNzdikNCg0KYGBge3J9DQp0ZXN0YmdsaXN0IDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvZW52L3VuaXF1ZV9jZWxsX2NlbnRyb2lkX2xvbmxhdF9uYWZvMl9kZXB0aC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KaGVhZCh0ZXN0YmdsaXN0KQ0KYGBgDQoNCmBgYHtyfQ0KYmFja29ic25vIDwtIG5yb3codGVzdGJnbGlzdCkNCmJhY2tvYnNubw0KYGBgDQoNCg0KDQojIHRoZSBpbmVmZmljZW50IGxvb3ANCg0KDQoNClRoaXMgbG9vcCBydW5zIHRocm91Z2ggdGhlIG5ldGNkZiBmaWxlcyBhbmQgdGhlbiBsb29rcyBmb3Igd2hpY2ggcm93cyBpbiBkYXRhX2FlYSBpdCBzaG91bGQgZXh0cmFjdCB0aGUgdmFsdWUgdG8gcG9pbnQgZnJvbSwgYW5kIGF0IHdoYXQgZGVwdGggKG5ldGNERiBsYXllcikNCg0KU3RhcnQgd2l0aCAyMDA3XzEwIGRhdGENCg0KYGBge3J9DQpzdHJ0IDwtIFN5cy50aW1lKCkgI2dldCB0aGUgc3RhcnQgdGltZQ0KDQp4eSA8LSB0ZXN0YmdsaXN0WyAsYygibG9uZ2l0dWRlXyIsImxhdGl0dWRlX20iKV0gIyBUaGlzIGlzIHRvIHRlbGwgUiB3aGVyZSB0aGUgY29vcmRpbmF0ZXMgYXJlLiBOb3RlIHRoYXQgdGhlIGNvbHVtbiBvcmRlciBuZWVkcyB0byBiZSBsb25naXR1ZGUsIGxhdGl0dWRlDQp0ZXN0YmdsaXN0c3AgPC0gU3BhdGlhbFBvaW50c0RhdGFGcmFtZShjb29yZHMgPSB4eSwgZGF0YSA9IHRlc3RiZ2xpc3QsIHByb2o0c3RyaW5nID0gQ1JTKCIrcHJvaj1hZWEgK2xhdF8xPTUwICtsYXRfMj03MCArbGF0XzA9NDAgK2xvbl8wPS02MCAreF8wPTAgK3lfMD0wICtlbGxwcz1HUlM4MCArZGF0dW09TkFEODMgK3VuaXRzPW0gK25vX2RlZnMiKSkgIyBUaGUgQ1JTIGlzIHVzZWQgaGVyZSBpcyBmb3IgdGhlIGFsYmVycyBlcXVhbCBhcmVhIHByb2plY3Rpb24uDQoNCg0KbmV0Y2RmX2xpc3QgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9lbnYvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IFRSVUUpICN0cnVlIG1lYW5zIHRoZSBmdWxsIHBhdGggaXMgaW5jbHVkZWQNCm5vX25ldGNkZiA8LSBsZW5ndGgobmV0Y2RmX2xpc3QpICNmb3IgdGhlIGxvb3AgLSBuZWVkIHRvIGtub3cgaG93IG1hbnkgZmlsZXMgdG8gY3ljbGUgdGhyb3VnaA0KbmV0Y2RmX25hbWUgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9lbnYvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IEZBTFNFKSAjZmFsc2UgbWVhbnMgdGhlIHBhdGggaXMgbm90IGluY2x1ZGVkDQphZWEgPC0gcmFzdGVyKCIuLi9vdXRwdXQvZW52L2FlYS50aWYiKSANCnlyIDwtIDIwMDcgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIHllYXINCm10aCA8LSAxMCAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24gbW9udGgNCg0KZm9yIChpIGluIDE6bm9fbmV0Y2RmKSB7ICANCiAgcHJpbnQobmV0Y2RmX25hbWVbaV0pICN0aGlzIGp1c3QgcHJpbnRzIHRoZSBuYW1lIG9mIHRoZSBuZXRDREYgUiBpcyB3b3JraW5nIG9uZQ0KICBicmt5ciA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMSkpICMgZXh0cmFjdGluZyB0aGUgZmlyc3QgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgeWVhcikNCiAgYnJrbXRoIDwtIGFzLmludGVnZXIoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAyKSkgIyBleHRyYWN0aW5nIHRoZSBzZWNvbmQgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgbW9udGgpDQogIGJya3ZhciA8LSAoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAzKSkgIyBleHRyYWN0aW5nIHRoZSB0aGlyZCBwYXJ0IG9mIHRoZSBuZXRjZGYgKGluYy5uYykNCiAgdGVtcF9icmljayA8LSBicmljayhuZXRjZGZfbGlzdFtpXSwgbHZhciA9IDQpDQogIHRlbXBfYnJpY2sgPC0gcHJvamVjdFJhc3Rlcih0ZW1wX2JyaWNrLCBhZWEpIA0KICAgIGZvciAoaiBpbiAxOm5yb3codGVzdGJnbGlzdHNwKSkgeyAgDQogICAgICBkZSA8LSB0ZXN0YmdsaXN0c3AkZGVwdGhsYXllcm5vW1tqXV0gICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIGRlcHRoIGxheWVyDQogICAgICAgICAgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAidGVtcC5uYyIpew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic2FsaW5pdHkubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAiY2hsLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm8yLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm1scC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG1scF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic3NoLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc3NoX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgIA0KICAgICAgICAgIH0NCiAgICAgDQogICAgfQ0KfQ0Kd3JpdGUuY3N2KHRlc3RiZ2xpc3RzcCwgIi4uL2RhdGEvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX2FsbGJhY2tncm91bmRwb2ludHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQp0ZXN0X2JhY2tfZGYgPC0gYXMuZGF0YS5mcmFtZSh0ZXN0YmdsaXN0c3ApDQpwcmludChTeXMudGltZSgpLXN0cnQpICN0aW1lIGl0IHRvb2sgdG8gcnVuDQpgYGANCg0Kb2sgbm93IGNyZWF0ZSB0aGUgZmlyc3QgbG90IG9mIHJhbmRvbSBmb3IgMjAwN18xMA0KDQpgYGB7cn0NCnRlc3RiazEwMDAwIDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMCksIF0gICN3aGVyZSAxMDAwMCA9IG51bWJlciBvZiByb3dzIHRvIHNhbXBsZSAobGFyZ2Ugc2FtcGxlIGFzIHBlciBtYXhlbnQpDQp0ZXN0YmsyMDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMjAwMDApLCBdICANCnRlc3RiazUwMDAwIDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCA1MDAwMCksIF0gIA0KdGVzdGJrMTAwMDAwIDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMDApLCBdICANCnRlc3RiazE5MDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTkwMDAwKSwgXSAgDQpgYGANCg0KDQoNCnBsb3QgZWFjaCB2YXJpYWJsZSBhZ2FpbnN0IHRoZSBkaWZmZXJlbnQgbm8gb2YgYmFja2dyb3VuZCBwb2ludHMNCg0KDQoNCmBgYHtyfQ0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IHNzaF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICsgbGFicyh4ID0gIlNlYSBTdXJmYWNlIEhlaWdodCBBYm92ZSBHZW9pZCAobWV0ZXJzKSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX3NzaF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gbWxwX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikgKyBsYWJzKHggPSAiTWl4ZWQgbGF5ZXIgdGhpY2tuZXNzIChNTFApIChtZXRlcnMpIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMDcxMF9tbHBfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUgDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSB0ZW1wX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikgICsgbGFicyh4ID0gIlRlbXBlcmF0dXJlIGF0IHN1cmZhY2UgKGtlbHZpbikiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX3RlbXBfc3VyZmFjZV9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gdGVtcF9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKSArIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSBhdCBzYW1wbGluZyBkZXB0aCAoa2VsdmluKSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfdGVtcF9kZXB0aF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gc2FsaW5pdHlfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKSArIGxhYnMoeCA9ICJTYWxpbml0eSBhdCBzdXJmYWNlIChrZWx2aW4pIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMDcxMF9zYWxpbml0eV9zdXJmYWNlX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKSArIGxhYnMoeCA9ICJTYWxpbml0eSBhdCBzYW1wbGluZyBkZXB0aCAoa2VsdmluKSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfc2FsaW5pdHlfZGVwdGhfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICsgbGFicyh4ID0gIkNobG9yb3BoeWxsIGNvbmNlbnRyYXRpb24gYXQgc3VyZmFjZSAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMDcxMF9jaGxfc3VyZmFjZV9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gY2hsX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICsgbGFicyh4ID0gIkNobG9yb3BoeWxsIGNvbmNlbnRyYXRpb24gYXQgc2FtcGxpbmcgZGVwdGggKG1tb2wubS0zKSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfY2hsX2RlcHRoX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBvMl9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICsgbGFicyh4ID0gIkRpc3NvbHZlZCBveHlnZW4gY29uY2VudHJhdGlvbiBhdCBzdXJmYWNlIChtbW9sLm0tMykiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX28yX3N1cmZhY2VfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICsgbGFicyh4ID0gIkRpc3NvbHZlZCBveHlnZW4gY29uY2VudHJhdGlvbiBhdCBzYW1wbGluZyBkZXB0aCAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMDcxMF9vMl9kZXB0aF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNClRyeSBhZ2FpbiBmb3IgYW5vdGhlciBtb250aCAtIHNheSAxOTk5IDAyIEFORCBhZ2FpbiAyMDE0IDA2DQoNClRoaXMgdGltZSBleHRyYWN0IHRoZSB2YWx1ZXMgZm9yIGFsbCBwb2ludHMgYW5kIHRoZW4gc3Vic2V0DQoNCmBgYHtyfQ0Kc3RydCA8LSBTeXMudGltZSgpICNnZXQgdGhlIHN0YXJ0IHRpbWUNCg0KeHkgPC0gdGVzdGJnbGlzdFsgLGMoImxvbmdpdHVkZV8iLCJsYXRpdHVkZV9tIildICMgVGhpcyBpcyB0byB0ZWxsIFIgd2hlcmUgdGhlIGNvb3JkaW5hdGVzIGFyZS4gTm90ZSB0aGF0IHRoZSBjb2x1bW4gb3JkZXIgbmVlZHMgdG8gYmUgbG9uZ2l0dWRlLCBsYXRpdHVkZQ0KdGVzdGJnbGlzdHNwIDwtIFNwYXRpYWxQb2ludHNEYXRhRnJhbWUoY29vcmRzID0geHksIGRhdGEgPSB0ZXN0YmdsaXN0LCBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9YWVhICtsYXRfMT01MCArbGF0XzI9NzAgK2xhdF8wPTQwICtsb25fMD0tNjAgK3hfMD0wICt5XzA9MCArZWxscHM9R1JTODAgK2RhdHVtPU5BRDgzICt1bml0cz1tICtub19kZWZzIikpICMgVGhlIENSUyBpcyB1c2VkIGhlcmUgaXMgZm9yIHRoZSBhbGJlcnMgZXF1YWwgYXJlYSBwcm9qZWN0aW9uLg0KDQoNCm5ldGNkZl9saXN0IDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvZW52L2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBUUlVFKSAjdHJ1ZSBtZWFucyB0aGUgZnVsbCBwYXRoIGlzIGluY2x1ZGVkDQpub19uZXRjZGYgPC0gbGVuZ3RoKG5ldGNkZl9saXN0KSAjZm9yIHRoZSBsb29wIC0gbmVlZCB0byBrbm93IGhvdyBtYW55IGZpbGVzIHRvIGN5Y2xlIHRocm91Z2gNCm5ldGNkZl9uYW1lIDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvZW52L2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBGQUxTRSkgI2ZhbHNlIG1lYW5zIHRoZSBwYXRoIGlzIG5vdCBpbmNsdWRlZA0KYWVhIDwtIHJhc3RlcigiLi4vb3V0cHV0L2Vudi9hZWEudGlmIikgDQp5ciA8LSAxOTk5ICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiB5ZWFyDQptdGggPC0gMDIgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIG1vbnRoDQoNCmZvciAoaSBpbiAxOm5vX25ldGNkZikgeyAgDQogIHByaW50KG5ldGNkZl9uYW1lW2ldKSAjdGhpcyBqdXN0IHByaW50cyB0aGUgbmFtZSBvZiB0aGUgbmV0Q0RGIFIgaXMgd29ya2luZyBvbmUNCiAgYnJreXIgPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDEpKSAjIGV4dHJhY3RpbmcgdGhlIGZpcnN0IHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIHllYXIpDQogIGJya210aCA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMikpICMgZXh0cmFjdGluZyB0aGUgc2Vjb25kIHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIG1vbnRoKQ0KICBicmt2YXIgPC0gKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMykpICMgZXh0cmFjdGluZyB0aGUgdGhpcmQgcGFydCBvZiB0aGUgbmV0Y2RmIChpbmMubmMpDQogIHRlbXBfYnJpY2sgPC0gYnJpY2sobmV0Y2RmX2xpc3RbaV0sIGx2YXIgPSA0KQ0KICB0ZW1wX2JyaWNrIDwtIHByb2plY3RSYXN0ZXIodGVtcF9icmljaywgYWVhKSANCiAgICBmb3IgKGogaW4gMTpucm93KHRlc3RiZ2xpc3RzcCkpIHsgIA0KICAgICAgZGUgPC0gdGVzdGJnbGlzdHNwJGRlcHRobGF5ZXJub1tbal1dICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiBkZXB0aCBsYXllcg0KICAgICAgICAgIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInRlbXAubmMiKXsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNhbGluaXR5Lm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gImNobC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJvMi5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJtbHAubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRtbHBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNzaC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNzaF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICANCiAgICAgICAgICB9DQogICAgIA0KICAgIH0NCn0NCndyaXRlLmNzdih0ZXN0YmdsaXN0c3AsICIuLi9kYXRhL2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9hbGxiYWNrZ3JvdW5kcG9pbnRzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KdGVzdF9iYWNrX2RmIDwtIGFzLmRhdGEuZnJhbWUodGVzdGJnbGlzdHNwKQ0KcHJpbnQoU3lzLnRpbWUoKS1zdHJ0KSAjdGltZSBpdCB0b29rIHRvIHJ1bg0KYGBgDQoNCm9rIG5vdyBjcmVhdGUgdGhlIGZpcnN0IGxvdCBvZiByYW5kb20gZm9yIDE5OTlfMDINCg0KYGBge3J9DQp0ZXN0YmsxMDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDApLCBdICAjd2hlcmUgMTAwMDAgPSBudW1iZXIgb2Ygcm93cyB0byBzYW1wbGUgKGxhcmdlIHNhbXBsZSBhcyBwZXIgbWF4ZW50KQ0KdGVzdGJrMjAwMDAgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDIwMDAwKSwgXSAgDQp0ZXN0Yms1MDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgNTAwMDApLCBdICANCnRlc3RiazEwMDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDAwKSwgXSAgDQp0ZXN0YmsxOTAwMDAgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDE5MDAwMCksIF0gIA0KYGBgDQoNCmFuZCBwbG90DQoNCg0KYGBge3J9DQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gc3NoX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikgKyBsYWJzKHggPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IEFib3ZlIEdlb2lkIChtZXRlcnMpIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9zc2hfYmFjay5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IG1scF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICArIGxhYnMoeCA9ICJNaXhlZCBsYXllciB0aGlja25lc3MgKE1MUCkgKG1ldGVycykiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX21scC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IHRlbXBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKSArIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSBhdCBzdXJmYWNlIChrZWx2aW4pIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl90ZW1wX3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICsgbGFicyh4ID0gIlRlbXBlcmF0dXJlIGF0IHNhbXBsaW5nIGRlcHRoIChrZWx2aW4pIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl90ZW1wX2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gc2FsaW5pdHlfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3NhbGluaXR5X3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3NhbGluaXR5X2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gY2hsX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9jaGxfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IGNobF9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9jaGxfZGVwdGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBvMl9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX28yX3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBvMl9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9vMl9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQoNCkFuZCBub3cgMjAxNF8wNg0KDQoNCmBgYHtyfQ0Kc3RydCA8LSBTeXMudGltZSgpICNnZXQgdGhlIHN0YXJ0IHRpbWUNCg0KeHkgPC0gdGVzdGJnbGlzdFsgLGMoImxvbmdpdHVkZV8iLCJsYXRpdHVkZV9tIildICMgVGhpcyBpcyB0byB0ZWxsIFIgd2hlcmUgdGhlIGNvb3JkaW5hdGVzIGFyZS4gTm90ZSB0aGF0IHRoZSBjb2x1bW4gb3JkZXIgbmVlZHMgdG8gYmUgbG9uZ2l0dWRlLCBsYXRpdHVkZQ0KdGVzdGJnbGlzdHNwIDwtIFNwYXRpYWxQb2ludHNEYXRhRnJhbWUoY29vcmRzID0geHksIGRhdGEgPSB0ZXN0YmdsaXN0LCBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9YWVhICtsYXRfMT01MCArbGF0XzI9NzAgK2xhdF8wPTQwICtsb25fMD0tNjAgK3hfMD0wICt5XzA9MCArZWxscHM9R1JTODAgK2RhdHVtPU5BRDgzICt1bml0cz1tICtub19kZWZzIikpICMgVGhlIENSUyBpcyB1c2VkIGhlcmUgaXMgZm9yIHRoZSBhbGJlcnMgZXF1YWwgYXJlYSBwcm9qZWN0aW9uLg0KDQoNCm5ldGNkZl9saXN0IDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvZW52L2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBUUlVFKSAjdHJ1ZSBtZWFucyB0aGUgZnVsbCBwYXRoIGlzIGluY2x1ZGVkDQpub19uZXRjZGYgPC0gbGVuZ3RoKG5ldGNkZl9saXN0KSAjZm9yIHRoZSBsb29wIC0gbmVlZCB0byBrbm93IGhvdyBtYW55IGZpbGVzIHRvIGN5Y2xlIHRocm91Z2gNCm5ldGNkZl9uYW1lIDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvZW52L2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBGQUxTRSkgI2ZhbHNlIG1lYW5zIHRoZSBwYXRoIGlzIG5vdCBpbmNsdWRlZA0KYWVhIDwtIHJhc3RlcigiLi4vb3V0cHV0L2Vudi9hZWEudGlmIikgDQp5ciA8LSAyMDE0ICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiB5ZWFyDQptdGggPC0gMDYgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIG1vbnRoDQoNCmZvciAoaSBpbiAxOm5vX25ldGNkZikgeyAgDQogIHByaW50KG5ldGNkZl9uYW1lW2ldKSAjdGhpcyBqdXN0IHByaW50cyB0aGUgbmFtZSBvZiB0aGUgbmV0Q0RGIFIgaXMgd29ya2luZyBvbmUNCiAgYnJreXIgPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDEpKSAjIGV4dHJhY3RpbmcgdGhlIGZpcnN0IHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIHllYXIpDQogIGJya210aCA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMikpICMgZXh0cmFjdGluZyB0aGUgc2Vjb25kIHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIG1vbnRoKQ0KICBicmt2YXIgPC0gKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMykpICMgZXh0cmFjdGluZyB0aGUgdGhpcmQgcGFydCBvZiB0aGUgbmV0Y2RmIChpbmMubmMpDQogIHRlbXBfYnJpY2sgPC0gYnJpY2sobmV0Y2RmX2xpc3RbaV0sIGx2YXIgPSA0KQ0KICB0ZW1wX2JyaWNrIDwtIHByb2plY3RSYXN0ZXIodGVtcF9icmljaywgYWVhKSANCiAgICBmb3IgKGogaW4gMTpucm93KHRlc3RiZ2xpc3RzcCkpIHsgIA0KICAgICAgZGUgPC0gdGVzdGJnbGlzdHNwJGRlcHRobGF5ZXJub1tbal1dICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiBkZXB0aCBsYXllcg0KICAgICAgICAgIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInRlbXAubmMiKXsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNhbGluaXR5Lm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gImNobC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJvMi5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJtbHAubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRtbHBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNzaC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNzaF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICANCiAgICAgICAgICB9DQogICAgIA0KICAgIH0NCn0NCndyaXRlLmNzdih0ZXN0YmdsaXN0c3AsICIuLi9kYXRhL2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9hbGxiYWNrZ3JvdW5kcG9pbnRzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KdGVzdF9iYWNrX2RmIDwtIGFzLmRhdGEuZnJhbWUodGVzdGJnbGlzdHNwKQ0KcHJpbnQoU3lzLnRpbWUoKS1zdHJ0KSAjdGltZSBpdCB0b29rIHRvIHJ1bg0KYGBgDQoNCm9rIG5vdyBjcmVhdGUgdGhlIGZpcnN0IGxvdCBvZiByYW5kb20gZm9yIDIwMTRfMDYNCg0KYGBge3J9DQp0ZXN0YmsxMDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDApLCBdICAjd2hlcmUgMTAwMDAgPSBudW1iZXIgb2Ygcm93cyB0byBzYW1wbGUgKGxhcmdlIHNhbXBsZSBhcyBwZXIgbWF4ZW50KQ0KdGVzdGJrMjAwMDAgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDIwMDAwKSwgXSAgDQp0ZXN0Yms1MDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgNTAwMDApLCBdICANCnRlc3RiazEwMDAwMCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDAwKSwgXSAgDQp0ZXN0YmsxOTAwMDAgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDE5MDAwMCksIF0gIA0KYGBgDQoNCmFuZCBwbG90DQoNCg0KYGBge3J9DQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gc3NoX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikgKyBsYWJzKHggPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IEFib3ZlIEdlb2lkIChtZXRlcnMpIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9zc2gucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBtbHBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKSAgKyBsYWJzKHggPSAiTWl4ZWQgbGF5ZXIgdGhpY2tuZXNzIChNTFApIChtZXRlcnMpIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9tbHAucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSB0ZW1wX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikrIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSBhdCBzdXJmYWNlIChrZWx2aW4pIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl90ZW1wX3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpICArIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSBhdCBzYW1wbGluZyBkZXB0aCAoa2VsdmluKSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfdGVtcF9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IHNhbGluaXR5X3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9zYWxpbml0eV9zdXJmYWNlLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAsIGFlcyh4ID0gc2FsaW5pdHlfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9zYWxpbml0eV9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfY2hsX3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBjaGxfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9jaGxfZGVwdGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMCwgYWVzKHggPSBvMl9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfbzJfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwLCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfbzJfZGVwdGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KDQoNCiMgM2QgcGxvdCBiYWNrZ3JvdW5kIHBvaW50cw0KDQpgYGB7cn0NCmJjazIwMTRfMDZfM2QgPC0gcGxvdF9seSh4PSB0ZXN0YmsxMDAwMCRsb25naXR1ZGVfLCB5ID0gdGVzdGJrMTAwMDAkbGF0aXR1ZGVfbSwgeiA9IHRlc3RiazEwMDAwJGRlcHRobGF5ZXJubykNCmJjazIwMTRfMDZfM2QNCmBgYA0KDQojIDJkIHBsb3QgYmFja2dyb3VuZCBwb2ludHMNCg0KYGBge3J9DQpiY2sxMDAwMHBvaW50c18yZCA8LSBwbG90KHg9IHRlc3RiazEwMDAwJGxvbmdpdHVkZV8sIHkgPSB0ZXN0YmsxMDAwMCRsYXRpdHVkZV9tLCB4bGFiID0gIkxvbmdpdHVkZSAobWV0ZXJzKSIsIHlsYWIgPSAiTGF0aXR1ZGUgKG1ldGVycyIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay9iY2sxMDAwMHBvaW50c18yZC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA==